using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Xml;

namespace DiskGarden
{
	[Serializable]
	public class CategoryNode : Node
	{

		[XmlArrayItem("catalog")]
		public List<CategoryNode> Categories;

		[NonSerialized]
		[XmlArrayItem("volume")]
		public List<VolumeNode> Volumes;

		public CategoryNode()
		{
			this.name = name;
			this.type = NodeType.Category;
			Categories = new List<CategoryNode>();
			Volumes = new List<VolumeNode>();
		}

		public CategoryNode AddCategory(string name)
		{
			CategoryNode obj = new CategoryNode();
			obj.Parent = this;
			obj.name = name;
			obj.Date = DateTime.Now;
			Categories.Add(obj);
			Root.InvokeNodeAdded(obj);
			return obj;
		}

		public void AddVolume(string path, string volumeName)
		{
			DirectoryInfo D = new DirectoryInfo(path);

			VolumeNode volume = new VolumeNode();
			volume.Parent = this;
			volume.name = volumeName;
			volume.Path = D.FullName;
			volume.Date = D.CreationTime;
			volume.Attributes = D.Attributes;
			this.Volumes.Add(volume);
			Root.InvokeNodeAdded(volume);

			// katalogowanie plikow
			FileInfo[] tabF = D.GetFiles();
			foreach (FileInfo obj in tabF)
				volume.AddFile(obj);

			// katalogowanie podkatalogow
			DirectoryInfo[] tabD = D.GetDirectories();
			foreach (DirectoryInfo cDir in tabD)
				volume.AddDir(cDir);
		}

		public override void Move(CategoryNode newParent)
		{
			CategoryNode parent = this.Parent as CategoryNode;
			if (parent != null && newParent != parent)
			{
				parent.Categories.Remove(this);
				newParent.Categories.Add(this);
				this.Parent = newParent;
				Root.InvokeNodeMoved(this);
			}
		}

		protected override void UpdateTree(TreeNodeCollection nodeCollection)
		{
			UpdateTree(nodeCollection, Categories);
			UpdateTree(nodeCollection, Volumes);
		}

		public override void UpdateFileList(ListView listView)
		{
			listView.BeginUpdate();
			listView.Items.Clear();
			UpdateFileList(listView, Categories);
			UpdateFileList(listView, Volumes);
			listView.EndUpdate();
		}

		protected override void RebuildParents()
		{
			RebuildParents(Categories);
			RebuildParents(Volumes);
		}

		public override void RemoveChild(Node node)
		{
			bool deleted = false;
			if (node is CategoryNode)
				deleted = Categories.Remove(node as CategoryNode);
			else if (node is VolumeNode)
				deleted = Volumes.Remove(node as VolumeNode);

			if (deleted)
				Root.InvokeNodeDeleted(node);
		}

		public override void Sort()
		{
			this.Categories.Sort();
			this.Volumes.Sort();
		}

		internal virtual void WriteXml(XmlWriter xml)
		{
			base.WriteXmlAttributes(xml);
			base.WriteXmlTags(xml);
			if (Volumes != null && Volumes.Count > 0)
			{
				xml.WriteStartElement("volumes");
				for (int i = 0; i < Volumes.Count; i++)
				{
					xml.WriteStartElement("volume");
					Volumes[i].WriteXml(xml);
					xml.WriteEndElement();
				}
				xml.WriteEndElement();
			}

			if (Categories != null && Categories.Count > 0)
			{
				xml.WriteStartElement("categories");
				for (int i = 0; i < Categories.Count; i++)
				{
					xml.WriteStartElement("category");
					Categories[i].WriteXml(xml);
					xml.WriteEndElement();
				}
				xml.WriteEndElement();
			}
		}

		internal virtual void ReadXml(XmlReader xml)
		{
			base.ReadXmlAttributes(xml);
			xml.MoveToElement();
			if (xml.IsEmptyElement) return;
			string nodeName = xml.Name;
			while (xml.Read())
			{
				if (xml.NodeType == XmlNodeType.EndElement && xml.Name == nodeName)
					return;
				if (xml.NodeType == XmlNodeType.Element)
				{
					switch (xml.Name)
					{
						case "volumes":
							while (xml.Read())
							{
								if (xml.NodeType == XmlNodeType.EndElement && xml.Name == "volumes")
									break;
								if (xml.Name == "volume")
								{
									VolumeNode node = new VolumeNode();
									node.ReadXml(xml);
									Volumes.Add(node);
								}
							}
							break;
						case "categories":
							while (xml.Read())
							{
								if (xml.NodeType == XmlNodeType.EndElement && xml.Name == "categories")
									break;
								if (xml.Name == "category")
								{
									CategoryNode node = new CategoryNode();
									node.ReadXml(xml);
									Categories.Add(node);
								}
							}
							break;
						case "tags":
							ReadXmlTags(xml);
							break;
					}
				}
			}
		}
	}
}
